﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Data;
using Jb.Common.Extensions;
using Jb.Domain;
using Jb.Web.ViewModels;
using Jb.Web.Utility;
using AutoMapper;
using Jb.Web.ViewModels.UtilityModels;
using System.Text;

namespace Jb.Web.Areas.Private.Controllers
{
    [Authorize(Roles = "Company Admin,Company User,Admin")]
    public class JobApplicationController : BaseController
    {
		private JbEntities _Context = new JbEntities();
        
		#region Constructors
		public JobApplicationController()
		{
		}

		public JobApplicationController(UserViewModel currentUser)
			: base(currentUser)
        {
        }
		#endregion Constructors

		#region Action Methods

        /// <summary>
        /// Shows a List of Job Applications for a given job
        /// </summary>
        /// <param name="id"></param>
        /// <param name="pageNo"></param>
        /// <returns></returns>
        public ActionResult Index(int id = 0, int pageNo = 0)
        {
            Job entity = _Context.GetJobByID(id);
            JobViewModel job = Mapper.Map<Job, JobViewModel>(entity);
            ViewData[AppConstants.ViewDataKeys.SECONDARY_MODEL] = job;
            return View("List", BuildJobApplicationListConfig(id, pageNo));
        }

        /// <summary>
        /// Shows a List of Job Applications for a given job
        /// </summary>
        /// <param name="id"></param>
        /// <param name="pageNo"></param>
        /// <returns></returns>
		public ActionResult List(int id = 0, int pageNo = 0)
        {
            Job entity = _Context.GetJobByID(id);
            JobViewModel job = Mapper.Map<Job, JobViewModel>(entity);
            ViewData[AppConstants.ViewDataKeys.SECONDARY_MODEL] = job;
            return View(BuildJobApplicationListConfig(id, pageNo));
        }

        /// <summary>
        /// Gets a full list of jobs ordered by most applied applications
        /// List only currently published jobs
        /// </summary>
        /// <param name="pageNo"></param>
        /// <returns></returns>
        public ActionResult FullList(int pageNo = 0)
        {   
            UtilityDAO dao = new UtilityDAO();
            int totalRecord = 0;
            PagerConfig pager = new PagerConfig(pageNo <= 0 ? 1 : pageNo, ConfigReader.PageSize, totalRecord);
            Jb.Domain.DbParameter[] parameters = new[]{
                new Jb.Domain.DbParameter("@CompanyID", LoggedInUser.Contact.CompanyID)
            };
            DataSet ds = dao.GetPagedData(DbObject.SP.GET_PAGED_JOBAPPLICATIONS_BY_COMPANY, parameters, pager.PageNo, pager.PageSize, out totalRecord, true);
            pager.TotalRecord = totalRecord;
            ListConfig listConfig = new ListConfig(ds.Tables[0], pager);
            return View(listConfig);
        }
        /// <summary>
        /// Updates the Job application read status
        /// </summary>
        /// <param name="applicationID"></param>
        /// <returns>
        /// -1 -> Application Not found
        /// -2 -> Job and Company is different (Probable hacking attempt)
        /// -3 -> Already read, no need to update status
        /// +1 -> Status updated Successfully
        /// </returns>
        [HttpPost]
        public int UpdateReadStatus(int applicationID)
        {
            JobApplication application = _Context.JobApplications.Include("Job").FirstOrDefault(P => P.ID == applicationID);
            if (application == null)
                return -1;
            if (application.Job.CompanyID != LoggedInUser.Contact.CompanyID)
                return -2;

            if (application.HasRead)
                return -3;

            application.HasRead = true;
            _Context.SaveChanges();
            return 1;
        }

        /// <summary>
        /// Updates the Job application read status
        /// </summary>
        /// <param name="applicationID"></param>
        /// <returns>
        /// -1 -> Application Not found
        /// -2 -> Job and Company is different (Probable hacking attempt)
        /// -3 -> Already Shortlisted this application, no need to update short list status again
        /// +1 -> Short list Status updated Successfully
        /// </returns>
        [HttpPost]
        public int ShortListApplication(int applicationID)
        {
            JobApplication application = _Context.JobApplications.Include("Job").FirstOrDefault(P => P.ID == applicationID);
            if (application == null)
                return -1;
            if (application.Job.CompanyID != LoggedInUser.Contact.CompanyID)
                return -2;

            if (application.HasShortListed)
                return -3;

            application.HasShortListed = true;

            _Context.SaveChanges();
            return 1;
        }

        /// <summary>
        /// Sends an Interview Request to a Job Seeker
        /// </summary>
        /// <param name="id"></param>
        /// <param name="applicationID"></param>
        /// <param name="date"></param>
        /// <param name="hour"></param>
        /// <param name="minute"></param>
        /// <param name="message"></param>
        /// <returns>
        /// Returns an String with format [Status]:[RequestID] example 1:20. First part denotes as following
        /// -1 -> The requested Job Application was not found
        /// -2 -> Not this employers job. Probable hacking attempt
        /// -3 -> Requested Interview Request was not found
        /// -4 -> Unable to send the message
        /// +1 -> Message sent successfully
        /// </returns>
        [HttpPost]
        [ValidateInput(false)]
        public String SendInterviewRequest(int id, int applicationID, String date, int hour, int minute, String message)
        {
            JobApplication application = _Context.JobApplications.FirstOrDefault(P => P.ID == applicationID);
            if (application == null)
                return String.Format("{0}:{1}", -1, id);
            if (application.Job.CompanyID != LoggedInUser.Contact.CompanyID)
                return String.Format("{0}:{1}", -2, id);

            InterviewRequest request = null;
            if (id == 0)
            {
                request = new InterviewRequest();
                _Context.AddToInterviewRequests(request);
            }
            else
            {
                request = _Context.InterviewRequests.Include("JobApplication").FirstOrDefault(P => P.ID == id && P.ApplicationID == applicationID);
                if (request == null)
                    return String.Format("{0}:{1}", -3, id);
                ///Preventing Hacking attempt for resending failed interview request
                if (request.JobApplication.Job.CompanyID != LoggedInUser.Contact.CompanyID)
                    return String.Format("{0}:{1}", -2, id);
            }
            request.ApplicationID = applicationID;
            request.InvitedOn = DateTime.Now;
            request.InvitationDate = date.ToDateTime(ConfigReader.CSharpCalendarDateFormat);
            request.InvitationDate = new DateTime(request.InvitationDate.Year, request.InvitationDate.Month, request.InvitationDate.Day, hour, minute, 0);
            request.Message = message.Trim().IsNullOrEmpty() ? "N/A" : message.UrlDecode();
            ///Try to send the interview request email to the job seeker
            SendInterviewRequestMessage(request);
            _Context.SaveChanges();
            if(request.HasMessageSent)
                return String.Format("{0}:{1}", 1, request.ID);

            return String.Format("{0}:{1}", -4, request.ID);
        }

        /// <summary>
        /// Gets a Interview Request object
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public String GetInterviewRequest(int id)
        {
            InterviewRequest entity = _Context.InterviewRequests.Include("JobApplication").FirstOrDefault(P => P.ID == id);
            if (entity != null)
            {
                ///Preventing probable hacking attempt
                if (entity.JobApplication.Job.CompanyID != LoggedInUser.Contact.CompanyID)
                    return String.Empty;

                InterviewRequestViewModel viewModel = Mapper.Map<InterviewRequest, InterviewRequestViewModel>(entity);
                viewModel.InterviewHour = entity.InvitationDate.Hour;
                viewModel.InterviewMinute = entity.InvitationDate.Minute;
                return viewModel.ToJSON();
            }
            return String.Empty;
        }
		#endregion Action Methods
		
		#region Helper Methods

		/// <summary>
        /// Builds a ListConfig object with a list of JobApplications
        /// </summary>
        /// <returns></returns>
        private ListConfig BuildJobApplicationListConfig(int jobID, int pageNo)
		{            
            JobAppListType listType = JobAppListType.All;
            if (String.Compare(WebUtil.GetQueryStringValue("type"), "S", true) == 0)            
                listType = JobAppListType.ShortListed;
            else if (String.Compare(WebUtil.GetQueryStringValue("type"), "I", true) == 0)
                listType = JobAppListType.CalledForInterview;

			UtilityDAO dao = new UtilityDAO();
            int totalRecord = 0;
            PagerConfig pager = new PagerConfig(pageNo <=0 ? 1 : pageNo , ConfigReader.PageSize, totalRecord);
            Jb.Domain.DbParameter[] parameters = new[]{
                new Jb.Domain.DbParameter("@JobID", jobID)
                , new Jb.Domain.DbParameter("@ListType", (int)listType)
            };
            DataSet ds = dao.GetPagedData(DbObject.SP.GET_PAGED_JOBAPPLICATIONS_BY_JOB, parameters, pager.PageNo, pager.PageSize, out totalRecord, true);
            pager.TotalRecord = totalRecord;
            ListConfig listConfig = new ListConfig(ds.Tables[0], pager);
            return listConfig;
		}        

        /// <summary>
        /// Builds an Interview Request for the Corresponding job seeker and tries to send an email.
        /// Sets the Email Set status to the InterviewRequest object
        /// </summary>
        /// <param name="request"></param>
        private void SendInterviewRequestMessage(InterviewRequest request)
        {
            StringBuilder template = new StringBuilder(WebUtil.ReadEmailTemplate(AppConstants.EmailTemplate.COMMON));
            StringBuilder message = new StringBuilder(10);
            JobApplication application = _Context.JobApplications.Include("Job").Include("Resume").FirstOrDefault(P => P.ID == request.ApplicationID);

            message.AppendFormat("Hi {0},<br />", application.Resume.JobSeeker.Name.HtmlEncode());
            message.AppendFormat("You are invited for an interview on <b>{0}</b> for the following job:<br/><br/>", request.InvitationDate.ToString(AppConstants.ValueOf.DATE_FROMAT_DISPLAY_WITH_TIME));
            message.AppendFormat("<b>Job Info:</b><br/> <a href='{0}'>{1}</a><br/><br/>", 
                Url.JobDetailsUrl(application.Job.ID, application.Job.Url, null, true), WebUtil.FormatData(application.Job.Title));

            message.AppendFormat("<b>Message from the Employer:</b><br/><br/>{0}", WebUtil.FormatData(request.Message));
            template.Replace(AppConstants.ETConstants.MESSAGE, message.ToString());
            template.Replace(AppConstants.ETConstants.DOMAIN, WebUtil.GetDomainAddress());
            String subject = String.Format("Interview Request from {0}", application.Job.Company.Name.HtmlEncode());
            String fromEmail = LoggedInUser.Contact.Address.Email;
            String toEmail = application.Resume.JobSeeker.Address.Email;
            String cc = application.Job.Company.Address.Email;
            if (WebUtil.SendMail(fromEmail, toEmail, String.Empty, cc, subject, template.ToString()))
                request.HasMessageSent = true;
            else
                request.HasMessageSent = false;
        }
        #endregion			
    }
}


